#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
彩票调度器监控脚本 - 修复版本
提供实时任务状态监控和可视化界面
"""

import sys
import os
import time
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import json
from dotenv import load_dotenv


# 加载 .env 文件
env_path = os.path.join(os.path.dirname(__file__), '.env')
load_dotenv(env_path)

# 添加项目根目录到Python路径
root_path = os.getenv('ROOT_PATH', '')
if root_path:
    sys.path.append(root_path)
    print(f"✅ 已加载项目根目录: {root_path}")
else:
    print("⚠️ 未找到ROOT_PATH环境变量")


from crawler.database import db_manager
from crawler.config.settings import LOTTERY_TYPES

class SchedulerMonitor:
    """调度器监控类"""
    
    def __init__(self):
        self.lottery_names = {k: v.get('name', k) for k, v in LOTTERY_TYPES.items()}
        
        # 定义完整的调度配置
        self.schedule_config = {
            'fc3d': {
                'name': '福彩3D',
                'frequency': '每日',
                'fetch_time': '21:22',
                'update_time': '22:10',
                'active_days': list(range(7)),  # 每天 0-6
            },
            'ssq': {
                'name': '双色球',
                'frequency': '周二、周四、周日',
                'fetch_time': '21:22',
                'update_time': '22:10',
                'active_days': [1, 3, 6],  # 周二、周四、周日
            },
            'kl8': {
                'name': '快乐8',
                'frequency': '每日',
                'fetch_time': '21:40',
                'update_time': '22:10',
                'active_days': list(range(7)),  # 每天
            },
            'qlc': {
                'name': '七乐彩',
                'frequency': '周一、周三、周五',
                'fetch_time': '21:22',
                'update_time': '22:10',
                'active_days': [0, 2, 4],  # 周一、周三、周五
            },
            'dlt': {
                'name': '大乐透',
                'frequency': '周一、周三、周六',
                'fetch_time': '21:40',
                'update_time': '22:10',
                'active_days': [0, 2, 5],  # 周一、周三、周六
            },
            'pl3': {
                'name': '排列3',
                'frequency': '每日',
                'fetch_time': '21:40',
                'update_time': '22:10',
                'active_days': list(range(7)),  # 每天
            },
            'pl5': {
                'name': '排列5',
                'frequency': '每日',
                'fetch_time': '21:40',
                'update_time': '22:10',
                'active_days': list(range(7)),  # 每天
            },
            'qxc': {
                'name': '七星彩',
                'frequency': '周二、周五、周日',
                'fetch_time': '21:40',
                'update_time': '22:10',
                'active_days': [1, 4, 6],  # 周二、周五、周日
            }
        }
        
    def get_tasks_for_date(self, target_date: datetime) -> List[Dict]:
        """获取指定日期的所有任务"""
        tasks = []
        weekday = target_date.weekday()  # 0=周一, 6=周日
        
        for lottery_type, config in self.schedule_config.items():
            if weekday in config['active_days']:
                # 添加获取开奖结果任务
                fetch_time = datetime.combine(target_date.date(), 
                                            datetime.strptime(config['fetch_time'], '%H:%M').time())
                tasks.append({
                    'lottery_type': lottery_type,
                    'lottery_name': config['name'],
                    'action': '获取开奖结果',
                    'time': config['fetch_time'],
                    'datetime': fetch_time,
                    'status': self._get_task_status(lottery_type, 'fetch', config['fetch_time'], target_date)
                })
                
                # 添加更新奖项信息任务
                update_time = datetime.combine(target_date.date(), 
                                             datetime.strptime(config['update_time'], '%H:%M').time())
                tasks.append({
                    'lottery_type': lottery_type,
                    'lottery_name': config['name'],
                    'action': '更新奖项信息',
                    'time': config['update_time'],
                    'datetime': update_time,
                    'status': self._get_task_status(lottery_type, 'update', config['update_time'], target_date)
                })
        
        # 按时间排序
        tasks.sort(key=lambda x: x['datetime'])
        return tasks
    
    def get_next_jobs(self, days: int = 7, limit: int = 30) -> List[Dict]:
        """获取接下来几天的任务"""
        all_tasks = []
        
        # 从今天开始，获取接下来几天的任务
        base_date = datetime.now()
        for i in range(days):
            date = base_date + timedelta(days=i)
            daily_tasks = self.get_tasks_for_date(date)
            
            # 如果是今天，只显示还没执行的任务
            if i == 0:
                now = datetime.now()
                daily_tasks = [task for task in daily_tasks if task['datetime'] > now]
            
            all_tasks.extend(daily_tasks)
        
        return all_tasks[:limit]
    
    def get_latest_results(self, hours: int = 24) -> List[Dict]:
        """获取最近的开奖结果"""
        try:
            sql = """
            SELECT lottery_type, period, draw_date, 
                   CASE WHEN prize_info IS NULL THEN 0 ELSE 1 END as has_prize_info,
                   created_at, updated_at
            FROM lottery_results 
            WHERE created_at >= DATE_SUB(NOW(), INTERVAL %s HOUR)
            ORDER BY created_at DESC
            """
            results = db_manager.execute_query(sql, (hours,))
            
            for result in results:
                result['lottery_name'] = self.lottery_names.get(result['lottery_type'], result['lottery_type'])
                
            return results
        except Exception as e:
            print(f"获取最新结果失败: {e}")
            return []
    
    def _get_task_status(self, lottery_type: str, action: str, scheduled_time: str, target_date: datetime) -> str:
        """获取任务状态"""
        now = datetime.now()
        
        # 如果不是今天，显示等待状态
        if target_date.date() != now.date():
            return "⏳ 等待中"
        
        current_time = now.strftime("%H:%M")
        
        # 检查是否已过执行时间
        if current_time > scheduled_time:
            # 检查数据库中是否有今天的数据更新
            today_str = now.strftime('%Y-%m-%d')
            
            if action == 'fetch':
                # 检查是否有今天创建的记录
                sql = """
                SELECT COUNT(*) as count FROM lottery_results 
                WHERE lottery_type = %s AND DATE(created_at) = %s
                """
                results = db_manager.execute_query(sql, (lottery_type, today_str))
                if results and results[0]['count'] > 0:
                    return "✅ 已完成"
                else:
                    return "❌ 已超时"
            else:  # update
                # 检查是否有今天更新且包含prize_info的记录
                sql = """
                SELECT COUNT(*) as count FROM lottery_results 
                WHERE lottery_type = %s AND DATE(updated_at) = %s AND prize_info IS NOT NULL
                """
                results = db_manager.execute_query(sql, (lottery_type, today_str))
                if results and results[0]['count'] > 0:
                    return "✅ 已完成"
                else:
                    return "❌ 已超时"
        else:
            return "⏳ 等待中"
    
    def get_tasks_for_weekday(self, weekday_name: str, base_date: datetime = None) -> List[Dict]:
        """获取指定星期几的任务"""
        if base_date is None:
            base_date = datetime.now()
        
        # 计算目标日期
        weekday_map = {
            'monday': 0, 'tuesday': 1, 'wednesday': 2, 'thursday': 3,
            'friday': 4, 'saturday': 5, 'sunday': 6,
            '周一': 0, '周二': 1, '周三': 2, '周四': 3,
            '周五': 4, '周六': 5, '周日': 6
        }
        
        target_weekday = weekday_map.get(weekday_name.lower())
        if target_weekday is None:
            return []
        
        # 找到下一个目标星期几
        days_ahead = target_weekday - base_date.weekday()
        if days_ahead <= 0:  # 目标日期是今天或已过，取下周
            days_ahead += 7
        
        target_date = base_date + timedelta(days=days_ahead)
        return self.get_tasks_for_date(target_date)
    
    def print_dashboard(self):
        """打印监控面板"""
        os.system('clear' if os.name == 'posix' else 'cls')
        
        print("=" * 80)
        print("🎯 彩票调度器监控面板 (修复版)")
        print("=" * 80)
        print(f"⏰ 当前时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"📅 星期: {['一', '二', '三', '四', '五', '六', '日'][datetime.now().weekday()]}")
        print()
        
        # 今日任务状态
        print("📋 今日任务状态:")
        print("-" * 60)
        today_tasks = self.get_tasks_for_date(datetime.now())
        
        if today_tasks:
            for task in today_tasks:
                print(f"  {task['time']} | {task['lottery_name']:<8} | {task['action']:<12} | {task['status']}")
        else:
            print("  今日无开奖任务")
        
        print()
        
        # 明日任务预览
        tomorrow = datetime.now() + timedelta(days=1)
        tomorrow_tasks = self.get_tasks_for_date(tomorrow)
        print(f"📅 明日任务预览 ({tomorrow.strftime('%m-%d %A')}):")
        print("-" * 60)
        
        if tomorrow_tasks:
            for task in tomorrow_tasks:
                print(f"  {task['time']} | {task['lottery_name']:<8} | {task['action']:<12} | 计划执行")
        else:
            print("  明日无开奖任务")
        
        print()
        
        # 本周任务总览
        print("📊 本周任务总览:")
        print("-" * 80)
        
        weekdays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
        base_date = datetime.now()
        
        for i, weekday_name in enumerate(weekdays):
            # 计算该星期几的日期
            days_to_add = i - base_date.weekday()
            if days_to_add < 0:
                days_to_add += 7
            target_date = base_date + timedelta(days=days_to_add)
            
            daily_tasks = self.get_tasks_for_date(target_date)
            
            if daily_tasks:
                lottery_names = list(set([task['lottery_name'] for task in daily_tasks if task['action'] == '获取开奖结果']))
                print(f"  {weekday_name} ({target_date.strftime('%m-%d')}): {', '.join(lottery_names)} ({len(daily_tasks)}个任务)")
            else:
                print(f"  {weekday_name} ({target_date.strftime('%m-%d')}): 无开奖")
        
        print()
        
        # 最近执行结果
        print("📈 最近24小时执行结果:")
        print("-" * 60)
        recent_results = self.get_latest_results(24)
        
        if recent_results:
            for result in recent_results[:10]:
                prize_status = "✅ 完整" if result['has_prize_info'] else "⚠️ 部分"
                created_time = result['created_at'].strftime('%m-%d %H:%M') if result['created_at'] else 'N/A'
                print(f"  {created_time} | {result['lottery_name']:<8} | 期号:{result['period']:<8} | {prize_status}")
        else:
            print("  暂无执行记录")
        
        print()
        print("=" * 80)
        print("🔄 按 Ctrl+C 退出监控")
        print("=" * 80)
    
    def get_statistics(self) -> Dict:
        """获取统计信息"""
        try:
            # 今日总任务数
            today_tasks = self.get_tasks_for_date(datetime.now())
            total_today = len(today_tasks)
            completed_today = len([t for t in today_tasks if "已完成" in t['status']])
            
            # 最近7天的数据
            sql = """
            SELECT 
                DATE(created_at) as date,
                lottery_type,
                COUNT(*) as total_records,
                SUM(CASE WHEN prize_info IS NOT NULL THEN 1 ELSE 0 END) as complete_records
            FROM lottery_results 
            WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
            GROUP BY DATE(created_at), lottery_type
            ORDER BY date DESC
            """
            week_results = db_manager.execute_query(sql)
            
            return {
                'today_total': total_today,
                'today_completed': completed_today,
                'today_completion_rate': (completed_today / total_today * 100) if total_today > 0 else 0,
                'week_results': week_results
            }
        except Exception as e:
            print(f"获取统计信息失败: {e}")
            return {}
    
    def debug_tuesday_tasks(self):
        """专门调试周二任务的方法"""
        print("=== 🔍 周二任务详细调试 ===\n")
        
        # 获取下周二的日期
        now = datetime.now()
        days_to_tuesday = (1 - now.weekday()) % 7
        if days_to_tuesday == 0:  # 如果今天就是周二
            days_to_tuesday = 7
        
        tuesday_date = now + timedelta(days=days_to_tuesday)
        print(f"📅 调试日期: {tuesday_date.strftime('%Y-%m-%d')} (周二)")
        
        tuesday_tasks = self.get_tasks_for_date(tuesday_date)
        
        print(f"\n📊 周二任务总数: {len(tuesday_tasks)}")
        print("\n📋 详细任务列表:")
        
        for i, task in enumerate(tuesday_tasks, 1):
            print(f"  {i:2d}. {task['time']} | {task['lottery_name']:<8} | {task['action']}")
        
        # 按彩种分组统计
        lottery_tasks = {}
        for task in tuesday_tasks:
            lottery = task['lottery_name']
            if lottery not in lottery_tasks:
                lottery_tasks[lottery] = []
            lottery_tasks[lottery].append(task)
        
        print(f"\n📈 各彩种任务统计:")
        for lottery, tasks in lottery_tasks.items():
            print(f"  {lottery}: {len(tasks)}个任务")
        
        # 检查应该包含的彩种
        expected_lotteries = ['福彩3D', '快乐8', '排列3', '排列5', '双色球', '七星彩']
        actual_lotteries = list(lottery_tasks.keys())
        
        missing = [l for l in expected_lotteries if l not in actual_lotteries]
        if missing:
            print(f"\n⚠️ 缺少的彩种: {', '.join(missing)}")
        else:
            print(f"\n✅ 所有预期彩种都已包含")
        
        return tuesday_tasks
    
    def run_monitor(self, refresh_interval: int = 30):
        """运行监控界面"""
        try:
            while True:
                self.print_dashboard()
                time.sleep(refresh_interval)
        except KeyboardInterrupt:
            print("\n👋 监控已停止")

def main():
    """主函数"""
    import argparse
    
    parser = argparse.ArgumentParser(description="彩票调度器监控")
    parser.add_argument("--mode", choices=["dashboard", "status", "stats", "debug-tuesday"], default="dashboard",
                       help="监控模式")
    parser.add_argument("--refresh", type=int, default=30, help="刷新间隔(秒)")
    
    args = parser.parse_args()
    
    monitor = SchedulerMonitor()
    
    if args.mode == "dashboard":
        monitor.run_monitor(args.refresh)
    elif args.mode == "status":
        monitor.print_dashboard()
    elif args.mode == "stats":
        stats = monitor.get_statistics()
        print(json.dumps(stats, indent=2, default=str))
    elif args.mode == "debug-tuesday":
        monitor.debug_tuesday_tasks()

if __name__ == "__main__":
    main()
